package com.ruoyi.mes.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.mes.domain.*;
import com.ruoyi.mes.mapper.*;
import com.ruoyi.mes.service.IProInfoService;
import com.ruoyi.mes.utils.AvgUtils;
import com.ruoyi.mes.utils.CodeUtils;
import com.ruoyi.mes.vo.device.AvgUDPVo;
import com.ruoyi.mes.vo.product.BomMtrVo;
import com.ruoyi.mes.vo.product.TecProceVo;
import com.ruoyi.mes.vo.wksp.StartVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.mes.service.IWkspTaskService;
import org.springframework.transaction.annotation.Transactional;

import static com.ruoyi.common.core.domain.AjaxResult.DATA_TAG;

/**
 * 车间任务Service业务层处理
 *
 * @author LongAndHao
 * @date 2023-04-04
 */
@Service
public class WkspTaskServiceImpl implements IWkspTaskService {

    @Value("${ruoyi.taskCodeLast}")
    private int taskCodeLast;


    @Autowired
    private ProgPlanMapper progPlanMapper;

    @Autowired
    private ProgPlanDetailMapper progPlanDetailMapper;

    @Autowired
    private ProOrderMapper proOrderMapper;

    @Autowired
    private ProInfoServiceImpl proInfoService;

    @Autowired
    private ProInfoMapper proInfoMapper;

    @Autowired
    private WkspTaskMapper wkspTaskMapper;

    @Autowired
    private PickInfoMapper pickInfoMapper;

    @Autowired
    private TaskCartMapper taskCartMapper;

    @Autowired
    private RevokePickServiceImpl revokePickService;

    @Autowired
    private FinishInhouMapper finishInhouMapper;



    /**
     * 查询车间任务
     *
     * @param id 车间任务主键
     * @return 车间任务
     */
    @Override
    public WkspTask selectWkspTaskById(Long id) {
        return wkspTaskMapper.selectWkspTaskById(id);
    }

    /**
     * 查询车间任务列表
     *
     * @param wkspTask 车间任务
     * @return 车间任务
     */
    @Override
    public List<WkspTask> selectWkspTaskList(WkspTask wkspTask) {
        List<WkspTask> wkspTasks = wkspTaskMapper.selectWkspTaskList(wkspTask);
        if (wkspTasks.size() != 0) {
            for (WkspTask task : wkspTasks) {
                //计算生产进度
                task.setProductionSchedule((float) task.getWkspReadyQuantity() / task.getWkspPlanQuantity() * 100);

                //查询产品信息
                ProInfo proInfo = proInfoMapper.selectProInfoById(task.getProId());
                task.setProInfo(proInfo);
                //查询订单信息
                ProgPlanDetail progPlanDetail = progPlanDetailMapper.selectProgPlanDetailById(task.getProgDetailId());
                ProgPlan progPlan = progPlanMapper.selectProgPlanById(progPlanDetail.getProgId());
                ProOrder proOrder = proOrderMapper.selectProOrdersByCodeAndProId(progPlan.getOrderNumber(), task.getProId());
                task.setProOrder(proOrder);
            }
        }
        return wkspTasks;
    }

    /**
     * 新增车间任务
     *
     * @param wkspTask 车间任务
     * @return 结果
     */
    @Override
    public int insertWkspTask(WkspTask wkspTask) {
        wkspTask.setCreateTime(DateUtils.getNowDate());
        return wkspTaskMapper.insertWkspTask(wkspTask);
    }

    /**
     * 修改车间任务
     *
     * @param wkspTask 车间任务
     * @return 结果
     */
    @Override
    public int updateWkspTask(WkspTask wkspTask) {
        wkspTask.setUpdateTime(DateUtils.getNowDate());
        return wkspTaskMapper.updateWkspTask(wkspTask);
    }

    /**
     * 批量删除车间任务
     *
     * @param ids 需要删除的车间任务主键
     * @return 结果
     */
    @Override
    public int deleteWkspTaskByIds(Long[] ids) {
        return wkspTaskMapper.deleteWkspTaskByIds(ids);
    }

    /**
     * 删除车间任务信息
     *
     * @param id 车间任务主键
     * @return 结果
     */
    @Override
    public int deleteWkspTaskById(Long id) {
        return wkspTaskMapper.deleteWkspTaskById(id);
    }


    /**
     * 领料清单
     *
     * @param id 车间任务id
     * @return
     */
    @Override
    public AjaxResult pickingList(Long id) {
        WkspTask wkspTask = wkspTaskMapper.selectWkspTaskById(id);
        R<BomMtrVo> bomAndMtr = proInfoService.getBomAndMtrByProId(wkspTask.getProId());
        for (MtrInfo mtr : bomAndMtr.getData().getMtrs()) {
            mtr.setMtrQuantity(mtr.getMtrQuantity() * wkspTask.getWkspPlanQuantity());
        }
        return AjaxResult.success(bomAndMtr.getData());
    }

    /**
     * 确认领料
     *
     * @param id 车间任务id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult confirmPicking(Long id) {
        //修改领料状态 已申请
        WkspTask wkspTask = wkspTaskMapper.selectWkspTaskById(id);
        wkspTask.setPickingStatus(1L);
        wkspTaskMapper.updateWkspTask(wkspTask);

        //领料信息
        R<BomMtrVo> bomAndMtr = proInfoService.getBomAndMtrByProId(wkspTask.getProId());
        String pickCode = CodeUtils.PickCodeCreat();
        for (MtrInfo mtr : bomAndMtr.getData().getMtrs()) {
            PickInfo pickInfo = new PickInfo();
            pickInfo.setWkspTaskId(id);
            pickInfo.setPickCode(pickCode);
            pickInfo.setWkspCode(wkspTask.getWkspCode());
            pickInfo.setMtrCode(mtr.getMtrCode());
            pickInfo.setMtrName(mtr.getMtrName());
            pickInfo.setPickQuantity(mtr.getMtrQuantity() * wkspTask.getWkspPlanQuantity());
            pickInfo.setIspicked(0L);//默认未领
            pickInfo.setRemark("测试数据");
            pickInfoMapper.insertPickInfo(pickInfo);
        }
        return AjaxResult.success("领料成功!");
    }


    /**
     * 生成任务卡
     *
     * @param startVo
     * @return
     */
    @Override
    @Transactional
    public AjaxResult start(StartVo startVo) {
        WkspTask wkspTask = wkspTaskMapper.selectWkspTaskById(startVo.getId());

        //查找工序
        List<TecProceVo> tecProceVos = proInfoService.getTecProceByProId(wkspTask.getProId()).getData();

        //根据计划生产数量，及拆分数量生成任务卡
        //任务卡编号生成数量：计划生产数量 / 拆分数量 余数 == 0 ？ 结果 ： 结果 + 1
        List<String> codes = new ArrayList<>();
        //余数
        int remainder = (int) (wkspTask.getWkspPlanQuantity() % startVo.getSplitQuantity());
        if (remainder == 0){
            for (int i = 0; i < (wkspTask.getWkspPlanQuantity() / startVo.getSplitQuantity()); i++) {
                String takCardCode = wkspTask.getWkspCode() + "-" + String.valueOf(taskCodeLast++);
                codes.add(takCardCode);
            }
        }else {
            for (int i = 0; i < (wkspTask.getWkspPlanQuantity() / startVo.getSplitQuantity()) +1; i++) {
                String takCardCode = wkspTask.getWkspCode() + "-" + String.valueOf(taskCodeLast++);
                codes.add(takCardCode);
            }
        }


        if (remainder != 0) {
            for (int i = 0; i < codes.size() - 1; i++) {
                for (int j = 0; j < startVo.getSplitQuantity(); j++) {
                    TaskCart taskCart = new TaskCart();
                    taskCart.setProgDetailId(wkspTask.getProgDetailId());
                    taskCart.setWkspTaskId(startVo.getId());
                    taskCart.setTakCardCode(codes.get(i));
                    taskCart.setTaskNeedRptNum((long) tecProceVos.size());//需报工次数为工序数
                    taskCart.setTaskReadyRptNum(0L);
                    taskCart.setRptProceSeque(-1L);//默认没有已报工的顺序
                    taskCart.setStartTime(startVo.getStartTime());
                    taskCart.setStatus(1L);//默认生产中
                    taskCart.setOverTime(startVo.getOverTime());
                    taskCart.setRemark("测试数据");
                    taskCartMapper.insertTaskCart(taskCart);
                }
            }

            for (int i = 0; i < remainder; i++) {
                TaskCart taskCart = new TaskCart();
                taskCart.setProgDetailId(wkspTask.getProgDetailId());
                taskCart.setWkspTaskId(startVo.getId());
                taskCart.setTakCardCode(codes.get(codes.size() - 1));
                taskCart.setTaskNeedRptNum((long) tecProceVos.size());//需报工次数为工序数
                taskCart.setTaskReadyRptNum(0L);
                taskCart.setRptProceSeque(-1L);//默认没有已报工的顺序
                taskCart.setStartTime(startVo.getStartTime());
                taskCart.setStatus(1L);//默认生产中
                taskCart.setOverTime(startVo.getOverTime());
                taskCart.setRemark("测试数据");
                taskCartMapper.insertTaskCart(taskCart);
            }
        }else {
            for (int i = 0; i < codes.size(); i++) {
                for (int j = 0; j < startVo.getSplitQuantity(); j++) {
                    TaskCart taskCart = new TaskCart();
                    taskCart.setProgDetailId(wkspTask.getProgDetailId());
                    taskCart.setWkspTaskId(startVo.getId());
                    taskCart.setTakCardCode(codes.get(i));
                    taskCart.setTaskNeedRptNum((long) tecProceVos.size());//需报工次数为工序数
                    taskCart.setTaskReadyRptNum(0L);
                    taskCart.setRptProceSeque(-1L);//默认没有已报工的顺序
                    taskCart.setStartTime(startVo.getStartTime());
                    taskCart.setStatus(1L);//默认生产中
                    taskCart.setOverTime(startVo.getOverTime());
                    taskCart.setRemark("测试数据");
                    taskCartMapper.insertTaskCart(taskCart);
                }
            }
        }

        wkspTask.setOperationStatus(1L);
        wkspTaskMapper.updateWkspTask(wkspTask);

        //生成任务卡后调取小车工具类派遣小车
        AvgUtils.DispatchAvg();

        return AjaxResult.success("成功开工!");
    }


    /**
     * 撤回车间任务卡
     *
     * @param id 车间任务id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult revokeTaskCart(Long id) {
        List<TaskCart> taskCarts = taskCartMapper.selectTaskCartByWskpTaskId(id);
        //任务卡是否已有报工： 报工次数
        for (TaskCart taskCart : taskCarts) {
            if (taskCart.getTaskReadyRptNum() !=0){
                return AjaxResult.error("任务卡已报工，无法撤回!");
            }
        }

        //删除任务卡
        for (TaskCart taskCart : taskCarts) {
            taskCartMapper.deleteTaskCartByTaskCardId(taskCart.getTaskCardId());
        }
        WkspTask wkspTask = wkspTaskMapper.selectWkspTaskById(id);
        wkspTask.setOperationStatus(0L);
        wkspTaskMapper.updateWkspTask(wkspTask);

        return AjaxResult.success("撤回成功!");
    }


    /**
     * 删 - 车间任务 (是否已领料)
     * @param id 车间任务id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult deleteWskpTask(Long id) {
        WkspTask wkspTask = wkspTaskMapper.selectWkspTaskById(id);
        //若未申请 则直接删除车间任务
        if (wkspTask.getPickingStatus() == 0){
            wkspTaskMapper.deleteWkspTaskById(id);
        }else if(wkspTask.getPickingStatus() == 1){
            //若已申请,删除领料出库信息，再删车间任务
            List<PickInfo> pickInfos = pickInfoMapper.selectPickInfoByWkspTaskId(id);
            for (PickInfo pickInfo : pickInfos) {
                pickInfoMapper.deletePickInfoById(pickInfo.getId());
            }
            wkspTaskMapper.deleteWkspTaskById(id);
        }else if (wkspTask.getPickingStatus() == 2){
            //若已领料,则返回物料
            revokePickService.revokeMtr(wkspTask);

            wkspTaskMapper.deleteWkspTaskById(id);
        }
        //更改计划明细状态
        ProgPlanDetail progPlanDetail = progPlanDetailMapper.selectProgPlanDetailById(wkspTask.getProgDetailId());
        progPlanDetail.setStatus(0L);
        progPlanDetailMapper.updateProgPlanDetail(progPlanDetail);


        return AjaxResult.success("删除成功!");
    }


    /**
     * 完工入库 (车间任务卡已完工)
     * @param id 车间任务id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult finishInhou(Long id) {
        WkspTask wkspTask = wkspTaskMapper.selectWkspTaskById(id);

        //往完工入库表中新增数据
        FinishInhou finishInhou = new FinishInhou();
        finishInhou.setProId(wkspTask.getProId());
        finishInhou.setWkspTaskId(id);
        finishInhou.setInhouName(SecurityUtils.getLoginUser().getUser().getNickName());
        finishInhou.setWkspCode(wkspTask.getWkspCode());
        finishInhou.setInhouQuantity(wkspTask.getWkspReadyQuantity());
        finishInhou.setStatus(0L);//默认未入库
        finishInhouMapper.insertFinishInhou(finishInhou);

        return AjaxResult.success();
    }
}
